home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2007 September / PCWSEP07.iso / Software / Linux / Linux Mint 3.0 Light / LinuxMint-3.0-Light.iso / casper / filesystem.squashfs / usr / lib / hplip / base / async.py < prev    next >
Encoding:
Python Source  |  2007-04-04  |  10.4 KB  |  342 lines

  1. # -*- coding: utf-8 -*-
  2. #
  3. #   Id: asyncore.py,v 2.51 2000/09/07 22:29:26 rushing Exp
  4. # Modified for hplips 2003/06/20
  5. #   Author: Sam Rushing <rushing@nightmare.com>
  6.  
  7. # ======================================================================
  8. # Copyright 1996 by Sam Rushing
  9. #
  10. #                         All Rights Reserved
  11. #
  12. # Permission to use, copy, modify, and distribute this software and
  13. # its documentation for any purpose and without fee is hereby
  14. # granted, provided that the above copyright notice appear in all
  15. # copies and that both that copyright notice and this permission
  16. # notice appear in supporting documentation, and that the name of Sam
  17. # Rushing not be used in advertising or publicity pertaining to
  18. # distribution of the software without specific, written prior
  19. # permission.
  20. #
  21. # SAM RUSHING DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  22. # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
  23. # NO EVENT SHALL SAM RUSHING BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24. # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  25. # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
  26. # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  27. # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  28. # ======================================================================
  29. #
  30. # (c) Copyright 2003-2007 Hewlett-Packard Development Company, L.P.
  31. #
  32. # This program is free software; you can redistribute it and/or modify
  33. # it under the terms of the GNU General Public License as published by
  34. # the Free Software Foundation; either version 2 of the License, or
  35. # (at your option) any later version.
  36. #
  37. # This program is distributed in the hope that it will be useful,
  38. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40. # GNU General Public License for more details.
  41. #
  42. # You should have received a copy of the GNU General Public License
  43. # along with this program; if not, write to the Free Software
  44. # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  45. #
  46. # Modified by: Don Welch
  47. #
  48.  
  49. """
  50. Basic infrastructure for asynchronous socket service clients and servers.
  51.  
  52. There are only two ways to have a program on a single processor do "more
  53. than one thing at a time".  Multi-threaded programming is the simplest and
  54. most popular way to do it, but there is another very different technique,
  55. that lets you have nearly all the advantages of multi-threading, without
  56. actually using multiple threads. it's really only practical if your program
  57. is largely I/O bound. If your program is CPU bound, then pre-emptive
  58. scheduled threads are probably what you really need. Network servers are
  59. rarely CPU-bound, however.
  60.  
  61. If your operating system supports the select() system call in its I/O
  62. library (and nearly all do), then you can use it to juggle multiple
  63. communication channels at once; doing other work while your I/O is taking
  64. place in the "background."  Although this strategy can seem strange and
  65. complex, especially at first, it is in many ways easier to understand and
  66. control than multi-threaded programming. The module documented here solves
  67. many of the difficult problems for you, making the task of building
  68. sophisticated high-performance network servers and clients a snap.
  69.  
  70. NOTICE: This copy of asyncore has been modified from the Python Std Lib version.
  71.  
  72. """
  73.  
  74.  
  75. from g import *
  76. from codes import *
  77. import select, socket, sys, time, os, thread, fcntl
  78. from errno import EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, \
  79.      ENOTCONN, ESHUTDOWN, EINTR, EISCONN
  80.  
  81. socket_map = {}
  82.  
  83. class ExitNow(Exception):
  84.     pass
  85.  
  86.  
  87.  
  88. def loop(timeout=1.0, sleep_time=0.1):
  89.     while socket_map:
  90.         #log.debug( "async loop: %f" % time.time() )
  91.         r = []; w = []; e = []
  92.         for fd, obj in socket_map.items():
  93.             if obj.readable():
  94.                 r.append(fd)
  95.             if obj.writable():
  96.                 w.append(fd)
  97.         if [] == r == w == e:
  98.             time.sleep(timeout)
  99.         else:
  100.             try:
  101.                 r,w,e = select.select(r, w, e, timeout)
  102.             except select.error, err:
  103.                 if err[0] != EINTR:
  104.                     raise Error(ERROR_INTERNAL)
  105.                 r = []; w = []; e = []
  106.  
  107.         for fd in r:
  108.             try:
  109.                 obj = socket_map[fd]
  110.             except KeyError:
  111.                 continue
  112.  
  113.             try:
  114.                 obj.handle_read_event()
  115.             except ExitNow:
  116.                 raise ExitNow
  117.             except Error, e:
  118.                 obj.handle_error(e)
  119.  
  120.         for fd in w:
  121.             try:
  122.                 obj = socket_map[fd]
  123.             except KeyError:
  124.                 continue
  125.  
  126.             try:
  127.                 obj.handle_write_event()
  128.             except ExitNow:
  129.                 raise ExitNow
  130.             except Error, e:
  131.                 obj.handle_error(e)
  132.  
  133.             time.sleep(sleep_time)
  134.  
  135.  
  136.  
  137.  
  138. class dispatcher:
  139.     connected = False
  140.     accepting = False
  141.     closing = False
  142.     addr = None
  143.  
  144.     def __init__ (self, sock=None):
  145.         if sock:
  146.             self.set_socket(sock) 
  147.             self.socket.setblocking(0)
  148.             self.connected = True
  149.             try:
  150.                 self.addr = sock.getpeername()
  151.             except socket.error:
  152.                 # The addr isn't crucial
  153.                 pass
  154.         else:
  155.             self.socket = None
  156.  
  157.     def __repr__ (self):
  158.         status = [self.__class__.__module__+"."+self.__class__.__name__]
  159.         if self.accepting and self.addr:
  160.             status.append ('listening')
  161.         elif self.connected:
  162.             status.append ('connected')
  163.         if self.addr is not None:
  164.             try:
  165.                 status.append ('%s:%d' % self.addr)
  166.             except TypeError:
  167.                 status.append (repr(self.addr))
  168.         return '<%s at %#x>' % (' '.join (status), id (self))
  169.  
  170.     def add_channel (self): 
  171.         global socket_map
  172.         socket_map[self._fileno] = self
  173.  
  174.     def del_channel(self): 
  175.         global socket_map
  176.         fd = self._fileno
  177.         if socket_map.has_key(fd):
  178.             del socket_map[fd]
  179.  
  180.     def create_socket(self, family, type):
  181.         self.family_and_type = family, type
  182.         self.socket = socket.socket (family, type)
  183.         self.socket.setblocking(0)
  184.         self._fileno = self.socket.fileno()
  185.         self.add_channel()
  186.  
  187.     def set_socket(self, sock): 
  188.         self.socket = sock
  189.         self._fileno = sock.fileno()
  190.         self.add_channel()
  191.  
  192.     def set_reuse_addr(self):
  193.         # try to re-use a server port if possible
  194.         try:
  195.             self.socket.setsockopt (
  196.                 socket.SOL_SOCKET, socket.SO_REUSEADDR,
  197.                 self.socket.getsockopt (socket.SOL_SOCKET,
  198.                                         socket.SO_REUSEADDR) | 1
  199.                 )
  200.         except socket.error:
  201.             pass
  202.  
  203.     # ==================================================
  204.     # predicates for select()
  205.     # these are used as filters for the lists of sockets
  206.     # to pass to select().
  207.     # ==================================================
  208.  
  209.     def readable (self):
  210.         return True
  211.  
  212.     def writable (self):
  213.         return True
  214.  
  215.     # ==================================================
  216.     # socket object methods.
  217.     # ==================================================
  218.  
  219.     def listen (self, num):
  220.         self.accepting = True
  221.         return self.socket.listen(num)
  222.  
  223.     def bind(self, addr):
  224.         self.addr = addr
  225.         return self.socket.bind(addr)
  226.  
  227.     def connect(self, address):
  228.         self.connected = False
  229.         err = self.socket.connect_ex(address)
  230.         if err in (EINPROGRESS, EALREADY, EWOULDBLOCK):
  231.             return
  232.         if err in (0, EISCONN):
  233.             self.addr = address
  234.             self.connected = True
  235.             self.handle_connect()
  236.         else:
  237.             raise socket.error, err
  238.  
  239.     def accept (self):
  240.         try:
  241.             conn, addr = self.socket.accept()
  242.             return conn, addr
  243.         except socket.error, why:
  244.             if why[0] == EWOULDBLOCK:
  245.                 pass
  246.             else:
  247.                 raise socket.error, why
  248.  
  249.     def send (self, data):
  250.         try:
  251.             result = self.socket.send(data)
  252.             return result
  253.         except socket.error, why:
  254.             if why[0] == EWOULDBLOCK:
  255.                 return 0
  256.             else:
  257.                 raise socket.error, why
  258.             return 0
  259.  
  260.     def recv(self, buffer_size):
  261.         try:
  262.             data = self.socket.recv (buffer_size)
  263.             if not data:
  264.                 # a closed connection is indicated by signaling
  265.                 # a read condition, and having recv() return 0.
  266.                 self.handle_close()
  267.                 return ''
  268.             else:
  269.                 return data
  270.         except socket.error, why:
  271.             # winsock sometimes throws ENOTCONN
  272.             if why[0] in [ECONNRESET, ENOTCONN, ESHUTDOWN]:
  273.                 self.handle_close()
  274.                 return ''
  275.             else:
  276.                 raise socket.error, why
  277.  
  278.     def close (self):
  279.         self.del_channel()
  280.         self.socket.close()
  281.  
  282.     # cheap inheritance, used to pass all other attribute
  283.     # references to the underlying socket object.
  284.     def __getattr__ (self, attr):
  285.         return getattr (self.socket, attr)
  286.  
  287.     def handle_read_event(self):
  288.         if self.accepting:
  289.             # for an accepting socket, getting a read implies
  290.             # that we are connected
  291.             if not self.connected:
  292.                 self.connected = True
  293.             self.handle_accept()
  294.         elif not self.connected:
  295.             self.handle_connect()
  296.             self.connected = True
  297.             self.handle_read()
  298.         else:
  299.             self.handle_read()
  300.  
  301.     def handle_write_event(self):
  302.         # getting a write implies that we are connected
  303.         if not self.connected:
  304.             self.handle_connect()
  305.             self.connected = True
  306.         self.handle_write()
  307.  
  308.     def handle_expt_event(self):
  309.         self.handle_expt()
  310.  
  311.     def handle_error(self, e):
  312.         #self.close()
  313.         log.error("Error processing request.")
  314.         #raise e
  315.         raise Error(ERROR_INTERNAL)#( e.msg, e.opt )
  316.  
  317.     def handle_expt(self):
  318.         raise Error
  319.  
  320.     def handle_read(self):
  321.         raise Error
  322.  
  323.     def handle_write(self):
  324.         raise Error
  325.  
  326.     def handle_connect(self):
  327.         raise Error
  328.  
  329.     def handle_accept(self):
  330.         raise Error
  331.  
  332.     def handle_close(self):
  333.         self.close()
  334.  
  335. def close_all(): 
  336.     global channels
  337.     for x in channels.values():
  338.         x.channels.close()
  339.     channels.clear()
  340.  
  341.  
  342.